#ifndef unigame_GameObject_h
#define unigame_GameObject_h

#include "Object.h"
#include "transform/Transform.h"
#include "AutoRelease.h"
#include "config/Def.h"
#include <list>

namespace unigame
{
	class Mesh;
	class Material;
	class ComponentHolder;
	class Component;

	enum GameObjectType
	{
		E_GAMEOBJECT_GOT,
		E_CAMERA_GOT,
	};

	enum GameObjectFlag
	{
		E_NOT_DESTROY_GOF = 1,
		E_TRANSFORM_CHANGE_GOF = 1 << 1,
	};

	class GameObject: public Object, public AutoRelease
	{
	public:
		virtual ~GameObject();

		void addChild(GameObject* obj);
		void removeChild(GameObject* obj);
		void removeFromFather();

		int32u childNumber()
		{
			return m_childNumber;
		}

		void father(GameObject* father)
		{
			m_father = father;
		}

		GameObject* father()
		{
			return m_father;
		}

		Transform& transform()
		{
			return m_transform;
		}

		static GameObject* create(const char* name)
		{
			return uni_new GameObject(name);
		}

		virtual void update();

		GameObject* operator [](const int32u index);
		GameObject* operator [](const char* name);

		char* name()
		{
			return m_name;
		}

		void name(const char* name);

		void enable();
			
		void disable();

		bool isEnable()
		{
			return m_enable;
		}

		void setVisiable(bool isVisible);

		bool isVisible()
		{
			return m_visible;
		}

		int32u type()
		{
			return m_type;
		}

		GameObject* next(bool hasChecked = false);

		void setDistroyable(bool isDistroyable)
		{
			if(isDistroyable)
			{
				clearFlag(E_NOT_DESTROY_GOF);
			}
			else
			{
				setFlag(E_NOT_DESTROY_GOF);
			}
		}

		bool isDistroyable()
		{
			return getFlag(E_NOT_DESTROY_GOF);
		}

		Mesh* mesh();
		Material* material();

		void mesh(Mesh* mesh);
		void material(Material* mat);

		int32u layer()
		{
			return m_layer;
		}

		void layer(int32u layer)
		{
			m_layer = layer;
		}

		void release();

		void addComponent(Component* com);

		ComponentHolder* getComponent(int32u type);
		Component* removeComponent(int32u type);

		void setFlag(int32u flag)
		{
			m_flag |= flag;
		}

		void clearFlag(int32u flag)
		{
			m_flag &= ~flag;
		}

		bool getFlag(int32u flag)
		{
			return (m_flag & flag) > 0;
		}

	protected:
		GameObject(const char* name);
		GameObject(const GameObject& obj);
		GameObject& operator =(const GameObject& obj);

		void onAddToFather(GameObject* father);
		void onRemoveFromFather(GameObject* father);
	
		void releaseGameObject()
		{
			AutoRelease::release();
		}

	protected:
		Transform m_transform;
		GameObject* m_father;
		GameObject* m_firstChild;
		GameObject* m_sibling;
		int32u m_childNumber;
		ComponentHolder* m_mesh;
		ComponentHolder* m_material;
		char* m_name;
		int32u m_type;
		std::list<ComponentHolder*> m_componentList;

		int32u m_layer;
		bool m_enable;
		bool m_visible;
		char m_flag;
	};
}
#endif